﻿Imports System.Text

Public Class PostParser
    Dim LocalBuffer As New List(Of Byte) 'I like to work with lists !
    Dim FStream As System.IO.FileStream
    Dim TotalWrite As Long = 0

    Private _StorageFolder As String
    Public Property StorageFolder() As String
        Get
            Return _StorageFolder
        End Get
        Set(ByVal value As String)
            _StorageFolder = value
        End Set
    End Property

    Private _HeaderLength As Integer
    Public Property HeaderLenght() As Integer
        Get
            Return _HeaderLength
        End Get
        Private Set(ByVal value As Integer)
            _HeaderLength = value
        End Set
    End Property

    Private _Header As List(Of Byte)
    Public Property Header() As List(Of Byte)
        Get
            Return _Header
        End Get
        Set(ByVal value As List(Of Byte))
            _Header = value
            If value IsNot Nothing Then
                Me.HeaderString = Encoding.ASCII.GetString(value.ToArray, 0, value.Count)
                Me.Init()
            End If
        End Set
    End Property

    Private _DataPosition As Integer
    Public Property DataPosition() As Integer
        Get
            Return _DataPosition
        End Get
        Private Set(ByVal value As Integer)
            _DataPosition = value
        End Set
    End Property

    Private _BinaryPosition As Integer
    Public Property BinaryPosition() As Integer
        Get
            Return _BinaryPosition
        End Get
        Private Set(ByVal value As Integer)
            _BinaryPosition = value
        End Set
    End Property

    Private _BinaryLength As Long
    Public Property BinaryLength() As Long
        Get
            Return _BinaryLength
        End Get
        Private Set(ByVal value As Long)
            _BinaryLength = value
        End Set
    End Property

    Private _HeaderString As String
    Public Property HeaderString() As String
        Get
            Return _HeaderString
        End Get
        Private Set(ByVal value As String)
            _HeaderString = value
        End Set
    End Property

    Private _ContentLength As Long
    Public Property ContentLength() As Long
        Get
            Return _ContentLength
        End Get
        Private Set(ByVal value As Long)
            _ContentLength = value
        End Set
    End Property

    Private _Boundary As String
    Public Property Boundary() As String
        Get
            Return _Boundary
        End Get
        Private Set(ByVal value As String)
            _Boundary = value
        End Set
    End Property

    Private _FileName As String
    Public Property FileName() As String
        Get
            Return _FileName
        End Get
        Private Set(ByVal value As String)
            _FileName = value
        End Set
    End Property

    Public Sub PushData(ByVal Binary As List(Of Byte))
        If Me.Header IsNot Nothing Then
            'Extract Data form Header
            Me.LocalBuffer = Header.Skip(Me.BinaryPosition).ToList
            Me.LocalBuffer.AddRange(Binary.AsEnumerable)
            Me.Header = Nothing
        Else
            Me.LocalBuffer = Binary.ToList
        End If

        'Saving 
        If TotalWrite + LocalBuffer.Count > Me.BinaryLength Then
            LocalBuffer = LocalBuffer.Take(Me.BinaryLength - TotalWrite).ToList
        End If
        If LocalBuffer.Count > 0 Then
            FStream.Write(LocalBuffer.ToArray, 0, LocalBuffer.Count)
            'FStream.Flush()
            TotalWrite += LocalBuffer.Count
        End If
    End Sub

    Public Sub Close()
        If Me.Header IsNot Nothing Then
            'Extract Data form Header
            Me.LocalBuffer = Header.Skip(Me.BinaryPosition).ToList
            LocalBuffer = LocalBuffer.Take(Me.BinaryLength - TotalWrite).ToList
            FStream.Write(LocalBuffer.ToArray, 0, LocalBuffer.Count)
            Me.Header = Nothing
        End If
        LocalBuffer = Nothing
        FStream.Close()
        FStream.Dispose()
    End Sub

    Private Sub Init()
        Dim FlatHeader = Me.Header.Select(Function(p) p.ToString).Aggregate(Function(s1, s2) s1 & "-" & s2)
        Dim CrLr = "13-10-13-10"
        Dim TempString1 As String = FlatHeader.Substring(0, FlatHeader.IndexOf(CrLr))
        Dim TempString2 As String = FlatHeader.Substring(0, FlatHeader.IndexOf(CrLr, FlatHeader.IndexOf(CrLr) + 1))

        Me.DataPosition = TempString1.Length - TempString1.Replace("-", "").Length + 4
        Me.BinaryPosition = TempString2.Length - TempString2.Replace("-", "").Length + 4
        Me.HeaderLenght = Me.DataPosition
        FillBoundary()
        FillContentLength()
        FillFileName()
        FillStorageLocation()

        Me.BinaryLength = Me.ContentLength - (Me.BinaryPosition - Me.DataPosition) - Me.Boundary.Length - 8

        FStream = New System.IO.FileStream(MobiminLib.FileManager.CombinePath(StorageFolder, Me.FileName), IO.FileMode.Create, IO.FileAccess.Write)
    End Sub

    Private Sub FillContentLength()
        Dim Pattenr = "Content\-Length\:(.*)"
        Dim Mat = RegularExpressions.Regex.Match(HeaderString, Pattenr, RegularExpressions.RegexOptions.IgnoreCase)
        Me.ContentLength = CLng(Mat.Groups.Item(1).Value)
    End Sub

    Private Sub FillBoundary()
        Dim Pattenr = "boundary\=(.*)"
        Dim Mat = RegularExpressions.Regex.Match(HeaderString, Pattenr, RegularExpressions.RegexOptions.IgnoreCase)
        Me.Boundary = Mat.Groups.Item(1).Value.Trim
    End Sub

    Private Sub FillFileName()
        Dim Pattenr = "filename\=(.*)"
        Dim Mat = RegularExpressions.Regex.Match(HeaderString, Pattenr, RegularExpressions.RegexOptions.IgnoreCase)
        Me.FileName = MobiminLib.URLDecode(Mat.Groups.Item(1).Value.Replace("""", "").Trim)
    End Sub

    Private Sub FillStorageLocation()
        Dim Pattenr = "POST\s(.*?)\s"
        Dim Mat = RegularExpressions.Regex.Match(HeaderString, Pattenr, RegularExpressions.RegexOptions.IgnoreCase)
        Me.StorageFolder = MobiminLib.FileManager.GetPhysicalPath(Mat.Groups.Item(1).Value.Trim)
    End Sub
End Class
